import json
import random
import math
import time
import threading
from datetime import datetime, timedelta
import requests

# 安全范围常量
SAFETY_RANGES = {
    'motor': {
        'temperature': {'min': 20, 'max': 70, 'warning': 60, 'critical': 65},  # 电机温度范围(°C)
        'current': {'min': -10, 'max': 10, 'warning': 8, 'critical': 9},      # 电机电流范围(A)
        'speed': {'min': -10, 'max': 10, 'warning': 8, 'critical': 9},        # 电机速度范围(rad/s)
        'torque': {'min': -20, 'max': 20, 'warning': 15, 'critical': 18}      # 电机扭矩范围(Nm)
    },
    'battery': {
        'level': {'min': 0, 'max': 100, 'warning': 30, 'critical': 20},       # 电池电量范围(%)
        'voltage': {'min': 20, 'max': 28, 'warning': 22, 'critical': 21},     # 电池电压范围(V)
        'temperature': {'min': 0, 'max': 45, 'warning': 40, 'critical': 43}   # 电池温度范围(°C)
    },
    'system': {
        'temperature': {'min': 0, 'max': 60, 'warning': 50, 'critical': 55},  # 系统温度范围(°C)
        'cpu_usage': {'min': 0, 'max': 100, 'warning': 80, 'critical': 90},   # CPU使用率范围(%)
        'memory_usage': {'min': 0, 'max': 100, 'warning': 80, 'critical': 90} # 内存使用率范围(%)
    },
    'gait': {
        'stride_length': {'min': 50, 'max': 300, 'warning': 250, 'critical': 280},  # 步幅范围(mm)
        'step_height': {'min': 20, 'max': 150, 'warning': 120, 'critical': 140},    # 步高范围(mm)
        'time_interval': {'min': 0.1, 'max': 1.0, 'warning': 0.8, 'critical': 0.9}, # 时间间隔范围(s)
        'point_count': {'min': 10, 'max': 2000, 'warning': 1500, 'critical': 1800}  # 点数范围
    },
    'motion': {
        'sway_angle': {'min': 0, 'max': 45, 'warning': 30, 'critical': 40}    # 晃动角度范围(°)
    }
}

# 后端服务器配置
BACKEND_URL = 'http://8.137.14.132:5000'  # 后端服务器地址

# 定义全局变量
MOCK_TOKEN = None

# 从文件中读取令牌或获取新令牌
def get_token_from_file_or_login():
    """从文件中读取令牌或者登录获取新令牌"""
    try:
        # 尝试从文件中读取令牌
        with open("token.txt", "r") as f:
            token = f.read().strip()
            print("已从文件中读取令牌")
            return token
    except FileNotFoundError:
        # 如果文件不存在，尝试登录获取新令牌
        print("令牌文件不存在，尝试登录获取新令牌...")
        try:
            from get_token import get_token
            token = get_token()
            if token:
                print("成功获取新令牌")
                return token
            else:
                print("获取令牌失败，使用默认令牌")
                return 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaXNfYWRtaW4iOmZhbHNlLCJ1c2VybmFtZSI6InRlc3QiLCJleHAiOjE3NDk1NjE4ODYsImlhdCI6MTc0OTQ3NTQ4Nn0.kt7hIDIg24VqxXYAMoU4nWbDvR-w2Rwci92wxqIMGNA'
        except Exception as e:
            print(f"登录获取令牌时出错: {str(e)}")
            return 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaXNfYWRtaW4iOmZhbHNlLCJ1c2VybmFtZSI6InRlc3QiLCJleHAiOjE3NDk1NjE4ODYsImlhdCI6MTc0OTQ3NTQ4Nn0.kt7hIDIg24VqxXYAMoU4nWbDvR-w2Rwci92wxqIMGNA'

# 初始化令牌
MOCK_TOKEN = get_token_from_file_or_login()

# 全局变量用于存储模拟数据的设置
simulator_settings = {
    'gait': {
        'stride_length': 150,  # 默认步幅
        'step_height': 75,     # 默认步高
        'time_interval': 0.5,  # 默认时间间隔
        'point_count': 800,    # 默认点数
        'result': '正常'       # 默认结果
    },
    'motor': {
        'temperature': [35, 36, 37, 38],  # 四个电机的温度
        'current': [2, 2.5, 1.8, 2.2],    # 四个电机的电流
        'speed': [5, 4.5, 5.2, 4.8],      # 四个电机的速度
        'torque': [8, 7.5, 8.2, 7.8],     # 四个电机的扭矩
        'position': [180, 185, 175, 182], # 四个电机的位置
        'mode': ['normal', 'normal', 'normal', 'normal']  # 四个电机的模式
    },
    'battery': {
        'level': 85,           # 电池电量百分比
        'voltage': 25.2,       # 电池电压
        'current': 1.5,        # 电池电流
        'temperature': 30      # 电池温度
    },
    'system': {
        'temperature': 40,     # 系统温度
        'cpu_usage': 45,       # CPU使用率
        'memory_usage': 60     # 内存使用率
    }
}

# 存储历史数据
historical_data = {
    'gait_data': [],  # 保存历史步态数据
    'robot_status': [], # 保存机器人状态数据
    'device_data': []  # 保存设备数据
}

# 向后端发送数据的函数
def send_to_backend(endpoint, data, method='POST'):
    """将数据发送到后端API"""
    global MOCK_TOKEN
    try:
        url = f"{BACKEND_URL}{endpoint}"
        headers = {
            'Content-Type': 'application/json',
            'Authorization': f'Bearer {MOCK_TOKEN}'
        }
        
        # 打印发送的数据内容
        print(f"发送数据到 {url}:")
        print(json.dumps(data, indent=2, ensure_ascii=False))
        
        if method.upper() == 'POST':
            response = requests.post(url, json=data, headers=headers, timeout=10)
        elif method.upper() == 'PUT':
            response = requests.put(url, json=data, headers=headers, timeout=10)
        elif method.upper() == 'GET':
            response = requests.get(url, headers=headers, timeout=10)
        else:
            print(f"不支持的HTTP方法: {method}")
            return False
        
        if response.status_code in [200, 201]:
            print(f"数据成功发送到后端 ({response.status_code})")
            try:
                print(f"后端响应: {response.json()}")
            except:
                print(f"后端响应: {response.text[:100]}")
            return True
        else:
            print(f"发送数据到后端失败: HTTP {response.status_code}")
            print(f"响应内容: {response.text[:500]}")
            
            # 如果是401未授权错误，尝试刷新令牌
            if response.status_code == 401:
                print("令牌可能已过期，尝试刷新...")
                try:
                    from get_token import get_token
                    new_token = get_token()
                    if new_token:
                        MOCK_TOKEN = new_token
                        print("令牌已刷新，尝试重新发送请求...")
                        # 递归调用自身，使用新令牌重试
                        return send_to_backend(endpoint, data, method)
                except Exception as e:
                    print(f"刷新令牌失败: {str(e)}")
            
            return False
    except Exception as e:
        print(f"发送数据到后端时出错: {str(e)}")
        import traceback
        print(traceback.format_exc())
        return False

# 生成电机数据
def generate_realistic_motor_data():
    """生成更真实的电机数据，基于设置的值并添加随机波动"""
    settings = simulator_settings['motor']
    
    motor_data = {
        'temperatures': [],
        'currents': [],
        'speeds': [],
        'torques': [],
        'positions': [],
        'modes': []
    }

    for i in range(4):
        # 添加一些随机变化来模拟真实波动
        temp_variation = random.uniform(-2, 2)
        motor_data['temperatures'].append(round(settings['temperature'][i] + temp_variation, 2))
        
        current_variation = random.uniform(-0.5, 0.5)
        motor_data['currents'].append(round(settings['current'][i] + current_variation, 2))
        
        speed_variation = random.uniform(-0.3, 0.3)
        motor_data['speeds'].append(round(settings['speed'][i] + speed_variation, 2))
        
        torque_variation = random.uniform(-0.8, 0.8)
        motor_data['torques'].append(round(settings['torque'][i] + torque_variation, 2))
        
        pos_variation = random.uniform(-5, 5)
        motor_data['positions'].append(round(settings['position'][i] + pos_variation, 2))
        
        # 使用设置的模式，有小概率随机变化
        if random.random() < 0.1:  # 10%的概率变化模式
            modes = ["normal", "warning", "error", "standby"]
            motor_data['modes'].append(random.choice(modes))
        else:
            motor_data['modes'].append(settings['mode'][i])

    return motor_data

# 生成系统数据
def generate_system_data():
    """生成系统相关的模拟数据，基于设置的值并添加随机波动"""
    settings = simulator_settings
    
    # 添加随机变化来模拟真实波动
    battery_level_var = random.uniform(-3, 3)
    battery_voltage_var = random.uniform(-0.3, 0.3)
    battery_current_var = random.uniform(-0.2, 0.2)
    battery_temp_var = random.uniform(-1, 1)
    system_temp_var = random.uniform(-2, 2)
    
    return {
        'battery_level': round(settings['battery']['level'] + battery_level_var, 2),
        'battery_voltage': round(settings['battery']['voltage'] + battery_voltage_var, 2),
        'battery_current': round(settings['battery']['current'] + battery_current_var, 2),
        'battery_temperature': round(settings['battery']['temperature'] + battery_temp_var, 2),
        'temperature': round(settings['system']['temperature'] + system_temp_var, 2),
        'cpu_usage': round(settings['system']['cpu_usage'] + random.uniform(-5, 5), 2),
        'memory_usage': round(settings['system']['memory_usage'] + random.uniform(-5, 5), 2),
    }

# 生成步态数据
def generate_gait_data(task_id=None):
    """生成步态数据，基于设置的值并添加随机波动"""
    settings = simulator_settings['gait']
    
    # 添加随机变化来模拟真实波动
    stride_length_var = random.uniform(-10, 10)
    step_height_var = random.uniform(-5, 5)
    time_interval_var = random.uniform(-0.05, 0.05)
    point_count_var = random.randint(-50, 50)
    
    # 有10%的概率改变结果
    result = settings['result']
    if random.random() < 0.1:
        result = '异常' if result == '正常' else '正常'
    
    gait_data = {
        'task_id': task_id or str(random.randint(1, 100)),
        'stride_length': round(settings['stride_length'] + stride_length_var, 2),
        'step_height': round(settings['step_height'] + step_height_var, 2),
        'time_interval': round(settings['time_interval'] + time_interval_var, 2),
        'point_count': round(settings['point_count'] + point_count_var),
        'result': result,
        'created_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    }
    
    # 将生成的数据保存到历史记录中
    if len(historical_data['gait_data']) >= 50:  # 限制最多保存50条记录
        historical_data['gait_data'].pop(0)  # 移除最旧的记录
    historical_data['gait_data'].append(gait_data)
    
    return gait_data

# 生成机器人状态数据
def generate_robot_status():
    """生成机器人状态数据"""
    motor_data = generate_realistic_motor_data()
    system_data = generate_system_data()
    
    # 生成IMU数据
    imu_data = {
        'acc': [
            round(random.uniform(-1, 1), 2),
            round(random.uniform(-1, 1), 2),
            round(random.uniform(-9.8, -9.6), 2)  # 考虑重力加速度
        ],
        'gyro': [
            round(random.uniform(-0.1, 0.1), 2),
            round(random.uniform(-0.1, 0.1), 2),
            round(random.uniform(-0.1, 0.1), 2)
        ]
    }
    
    status_data = {
        **system_data,
        'motor_temperatures': motor_data['temperatures'],
        'motor_currents': motor_data['currents'],
        'motor_positions': motor_data['positions'],
        'motor_speeds': motor_data['speeds'],
        'motor_torques': motor_data['torques'],
        'motor_modes': motor_data['modes'],
        'imu_data': imu_data,
        'running_status': 'running',
        'gps_latitude': 39.9042 + random.uniform(-0.01, 0.01),
        'gps_longitude': 116.4074 + random.uniform(-0.01, 0.01),
        'updated_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    }
    
    # 将生成的数据保存到历史记录中
    if len(historical_data['robot_status']) >= 50:  # 限制最多保存50条记录
        historical_data['robot_status'].pop(0)  # 移除最旧的记录
    historical_data['robot_status'].append(status_data)
    
    return status_data

# 生成告警数据
def generate_alert_data():
    """生成告警数据"""
    alert_types = ['系统', '电机', '电池', '传感器']
    alert_levels = ['low', 'medium', 'high']
    alert_messages = [
        '系统温度过高',
        '电机1温度异常',
        '电池电量低',
        '传感器数据异常',
        '电机电流过大',
        '系统内存使用率过高',
        'CPU使用率超限',
        '机身晃动过大'
    ]
    
    alert_data = {
        'type': random.choice(alert_types),
        'level': random.choice(alert_levels),
        'message': random.choice(alert_messages),
        'status': 'unprocessed',
        'created_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    }
    
    return alert_data

# 生成并保存数据
def generate_and_save_data(save_to_db=True):
    """生成数据并保存到后端"""
    print("生成并保存模拟数据...")
    
    # 生成机器人状态数据
    robot_status = generate_robot_status()
    
    # 生成步态数据
    gait_data = generate_gait_data()
    
    # 保存到后端
    if save_to_db:
        # 保存机器人状态
        robot_status_endpoint = '/api/robot/status/update'  # 更新为刚添加的端点
        print(f"正在发送机器人状态数据到 {BACKEND_URL}{robot_status_endpoint}")
        success = send_to_backend(robot_status_endpoint, robot_status, method='POST')
        print(f"机器人状态数据发送结果: {'成功' if success else '失败'}")
        
        # 保存步态数据 - 使用步态数据生成API
        # 注意：此API需要taskId参数，而不是完整的步态数据
        gait_data_endpoint = '/api/admin/generate_gait'
        gait_data_payload = {
            'taskId': '16'  # 使用固定的任务ID 16，对应我们创建的任务脚本
        }
        print(f"正在发送步态数据到 {BACKEND_URL}{gait_data_endpoint}")
        success = send_to_backend(gait_data_endpoint, gait_data_payload)
        print(f"步态数据发送结果: {'成功' if success else '失败'}")
        
        # 随机生成告警数据 (10%的概率)
        if random.random() < 0.1:
            alert_data = generate_alert_data()
            alert_endpoint = '/api/alerts'
            print(f"正在发送告警数据到 {BACKEND_URL}{alert_endpoint}")
            success = send_to_backend(alert_endpoint, alert_data, method='POST')
            print(f"告警数据发送结果: {'成功' if success else '失败'}")
            
    return {
        'robot_status': robot_status,
        'gait_data': gait_data
    }

# 定时任务线程类
class DataGenerationThread(threading.Thread):
    def __init__(self, interval=60, save_to_db=True):
        super().__init__(daemon=True)
        self.interval = interval
        self.save_to_db = save_to_db
        self.running = True
    
    def run(self):
        """定时生成数据的线程"""
        print(f"启动数据生成线程，间隔 {self.interval} 秒")
        while self.running:
            try:
                generate_and_save_data(save_to_db=self.save_to_db)
            except Exception as e:
                print(f"生成数据时出错: {str(e)}")
            
            time.sleep(self.interval)
    
    def stop(self):
        """停止线程"""
        self.running = False 